#define _GNU_SOURCE
#include "app_device.h"
#include "log/log.h"
#include "app_common.h"
#include "app_message.h"
#include "app_mqtt.h"
#include "app_pool.h"
#include "app_buffer.h"
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h> //file control

static Device *device = NULL;

Device *app_device_init(char *fileName)
{
    device = (Device *)malloc(sizeof(Device));
    device->fileName = fileName;
    device->fd = open(fileName, O_RDWR);
    device->upBuffer = app_buffer_init(1024);
    device->downBuffer = app_buffer_init(1024);
    device->isRunning = 0;
    device->lastWriteTime = 0;
    device->post_read = NULL;
    device->pre_write = NULL;

    return device;
}

static int send_task_func(void *arg)
{
    char charsBuf[128] = {0};
    // 从上行缓冲区读取数据
    int len = app_buffer_read(device->upBuffer, charsBuf, sizeof(charsBuf));
    if (len == -1)
    {
        log_error("read error,从上行缓冲区读取数据失败");
        return -1;
    }

    // 把数据转换成json格式
    char *json = app_message_charsToJSON(charsBuf, len);
    if (json == NULL)
    {
        log_error("json error,数据转换成json格式失败");
        return -1;
    }

    // 发送数据到MQTT
    if (app_mqtt_send(json) == -1)
    {
        log_error("mqtt send error,发送数据到MQTT失败");
        free(json);
        return -1;
    }

    free(json);
    return 0;
}

static void *read_thread_func(void *arg)
{
    while (device->isRunning)
    {
    
        char readBuf[128];
        // 读取蓝牙发来的数据
        ssize_t len = read(device->fd, readBuf, sizeof(readBuf));
        if (len == -1)
        {
            log_error("read error,读取设备文件失败");
            return NULL;
        }
        
        // 把蓝牙数据转换成字符数组
        if (len > 0 && device->post_read != NULL)
        {
            len = device->post_read(readBuf, len);
            if (len == -1)
            {
                log_error("post read error,设备数据读后处理失败");
                //return NULL;
            }
            // 将字符数组消息保存到上行缓冲区
            if (len > 0)
            {
                log_debug("读取到设备数据：%.*s", len, readBuf);
                app_buffer_write(device->upBuffer, readBuf, len);
                // 通过线程池把数据发送到MQTT
                app_pool_registerTask(send_task_func, NULL);
            }
            // len=0,表示读到的数据不完整，继续循环读取
        }
    }

    return NULL;
}

static int write_task_func(void *arg)
{
    char charsBuf[128] = {0};
    // 从下行缓冲区读取数据
    int len = app_buffer_read(device->downBuffer, charsBuf, sizeof(charsBuf));
    if (len == -1)
    {
        log_error("read error,从下行缓冲区读取数据失败");
        return -1;
    }

    if (len > 0 && device->pre_write != NULL)
    {
        len = device->pre_write(charsBuf, len);
        if (len == -1)
        {
            log_error("pre write error,设备数据写前处理失败");
            return -1;
        }
        // 将数据写入设备文件
        if (len > 0)
        {
            // 如果距离上次写入时间间隔小于200ms，则等待不够的时间
            long long distanceTime = app_common_getCurrentTime() - device->lastWriteTime;
            if (distanceTime < 200)
            {
                usleep((200 - distanceTime) * 1000);
            }

            if (write(device->fd, charsBuf, len) != (ssize_t)len)
            {
                log_error("write error,将数据写入设备文件失败");
                return -1;
            }
            log_debug("写入设备数据：%.*s", len, charsBuf);

            device->lastWriteTime = app_common_getCurrentTime();

            return 0;
        }
    }

    return -1;
}

static int receive_msg_callback(char *json)
{
    char charsBuf[128] = {0};
    // 把json转换成字符数组
    int len = app_message_jsonToChars(json, charsBuf, sizeof(charsBuf));
    if (len == -1)
    {
        log_error("jsonToChars error,把json转换成字符数组失败");
        return -1;
    }
    // 把字符数组保存到下行缓冲中
    if (app_buffer_write(device->downBuffer, charsBuf, len) == -1)
    {
        log_error("write error,把字符数组保存到下行缓冲中失败");
        return -1;
    }
    // 将消息数据保存到设备文件的任务交给线程池执行
    app_pool_registerTask(write_task_func, NULL);

    return 0;
}

int app_device_start()
{
    // 上行部分
    if (device->isRunning == 1)
    {
        log_debug("device is running");
        return 0;
    }
    device->isRunning = 1;
    // 创建一个线程用于不断读取设备数据
    int rc = pthread_create(&device->readThread, NULL, read_thread_func, NULL);
    if (rc != 0)
    {
        log_error("create read thread error ");
        return -1;
    }
    else
    {
        log_debug("create read thread success");
    }
    
    // 下行部分
    app_mqtt_registerRecvCallback(receive_msg_callback);
    
    log_debug("设备启动完成");
    return 0;
}

void app_device_destroy()
{
    //释放缓冲区
    app_buffer_free(device->upBuffer);
    app_buffer_free(device->downBuffer);
    //关闭文件描述符
    close(device->fd);
    //关闭线程
    pthread_cancel(device->readThread);
    //释放设备
    free(device);

}
